package com.rankeiot.dev.controller;


import com.rankeiot.core.Current;
import com.rankeiot.core.anno.Auth;
import com.rankeiot.core.anno.OperationLog;
import com.rankeiot.core.data.UserInfo;
import com.rankeiot.core.data.response.Resp;

import com.rankeiot.core.util.Captcha;
import com.rankeiot.core.util.JSONUtil;
import com.rankeiot.core.util.RsaUtil;
import com.rankeiot.core.util.StringUtil;
import com.rankeiot.dev.DevConfig;
import com.rankeiot.dev.DevMenu;
import com.rankeiot.dev.mode.GenOption;
import com.rankeiot.dev.mode.Model;
import com.rankeiot.dev.mode.Table;
import com.rankeiot.dev.service.DMServices;
import com.rankeiot.dev.service.ModelServices;
import com.rankeiot.platform.util.PasswordUtil;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.sagacity.sqltoy.SqlToyContext;
import org.sagacity.sqltoy.dao.SqlToyLazyDao;
import org.sagacity.sqltoy.utils.FileUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;


import javax.sql.DataSource;

import java.io.File;
import java.io.IOException;
import java.util.*;


//@Controller
//@Mapping("dev")
@Auth(DevMenu.MODELS)
@RestController
@RequestMapping("dev")
@RequiredArgsConstructor
public class DevController {


    final DMServices dmServices;

   final ModelServices modelServices;

   final DataSource dataSource;

   final SqlToyLazyDao dao;

   final SqlToyContext sqlToyContext;

   final ApplicationContext context;

    @GetMapping( "genConfig")
    public Resp genConfig() {
       // String basePackage = context.get//Solon.app().source().getPackage().getName();//.getPackageName();
        return Resp.of(new HashMap())
                .set("basePackage", DevConfig.basePackage);
    }

    @PutMapping("save")
    public Resp save(@RequestParam String id, @RequestBody Table table) throws Exception {
        File file = new File(modelServices.getModelDir(), id);
        if (!id.endsWith(".json")) {
            Resp.fail("文件名错误");
        }
        // StringUtil.write(file,JSON.toJSONString(table));
        String content = JSONUtil.toPrettyJSONString(table);//JSON.toJSONString(table, SerializerFeature.PrettyFormat);
        FileUtil.putStrToFile(content, file.getAbsolutePath(), "UTF-8");
        return Resp.ok();
    }

    @PostMapping("import")
    public Resp importFromTable(@NotBlank String module, int upType, String prefix, String tables) throws Exception {
        String dir = modelServices.getModelDir();
        if (module.indexOf(".") > -1 || module.indexOf("/") > -1) {
            Resp.fail("模块名称不合法");
        }
        dir = dir + module;
        File dirFile = new File(dir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        String[] tbs = tables.split(",");
        List<Table> tableList = new ArrayList<>();
        for (String tb : tbs) {
            Table table = modelServices.genTable(tb, prefix);
            if (table != null) {
                table.setModule(module);
                tableList.add(table);
            }
        }
        saveTables(tableList, upType);
        return Resp.ok();
    }

    private void saveTables(List<Table> tables, int upType) throws Exception {
        for (Table table : tables) {
            String dir = modelServices.getModelDir();
            String module = table.getModule();
            if (module.indexOf(".") > -1 || module.indexOf("/") > -1) {
                continue;
            }
            dir = dir + module;
            File dirFile = new File(dir);
            if (!dirFile.exists()) {
                dirFile.mkdirs();
            }
            File dist = new File(dirFile, table.getCode() + ".json");
            String content = "";
            if (dist.exists()) {
                switch (upType) {
                    case 1://覆盖
                        //StringUtil.write(dist, JSON.toJSONString(table));
                        content = JSONUtil.toPrettyJSONString(table);//JSON.toJSONString(table, SerializerFeature.PrettyFormat);
                        FileUtil.putStrToFile(content, dist.getAbsolutePath(), "UTF-8");
                        break;
                    case 2://更新
                        updateTable(table, JSONUtil.parseObject(FileUtil.readFileAsStr(dist, "UTF-8"), Table.class));
                        content = JSONUtil.toPrettyJSONString(table);
                        FileUtil.putStrToFile(content, dist.getAbsolutePath(), "UTF-8");
                        break;
                    case 3://跳过
                        break;
                    default:
                        break;
                }
            } else {
                content = JSONUtil.toPrettyJSONString(table);
                FileUtil.putStrToFile(content, dist.getAbsolutePath(), "UTF-8");
            }
        }
    }

    /**
     * 更新设计
     *
     * @param newTable
     * @param old
     */
    private void updateTable(Table newTable, Table old) {

    }

    @RequestMapping( value = "models",method = {RequestMethod.GET,RequestMethod.POST})
    public Resp models() {
        return modelServices.loadModels();
    }

    @DeleteMapping("del")
    public Resp delete(String id) {
        File f = new File(modelServices.getModelDir() + id);
        if (!f.exists()) {
            Resp.fail("文件不存在");
        }
        if (f.isDirectory()) {
            Resp.fail("文件错误");
        }
        f.delete();
        return Resp.ok();
    }

    @GetMapping("detail")
    public Resp detail(String id) throws IOException {
        File f = new File(modelServices.getModelDir() + id);
        if (!f.exists()) {
            Resp.fail("文件不存在");
        }
        String content = FileUtil.readFileAsStr(f, "utf-8");
        return Resp.of(JSONUtil.parseObject(content));
    }

    @PostMapping( "gen")
    public Resp gen(@RequestBody GenOption option) {
        return modelServices.generate(option.getId(), option);
    }
    @PostMapping( "uniGen")
    public Resp uniGen(String id) {
       return Resp.ok("hello");
    }
    @PostMapping("tables")
    public Resp tables() {
        return modelServices.loadTables();
    }

    private String getContent(MultipartFile uf) throws IOException {
        return  StringUtil.read(uf.getInputStream());
    }

    @PostMapping("sql")
    public Resp sql(String sql) {
        if (dataSource == null) {
            return Resp.of(new ArrayList<>());
        }
        List result = dao.findBySql(sql, new HashMap<>());
        return Resp.of(result);
    }

    @GetMapping("dicts")
    public Resp dicts() {
        List result = dao.query()
                .sql("select sn `key`,name title from t_dictionary where type='dict'")
                .resultType(Map.class)
                .find();
        return Resp.of(result);
    }

    @GetMapping("translates")
    public Resp translates() {
        Set<String> names = sqlToyContext.getTranslateManager().getCacheNames();
        names.remove("dict");
        return Resp.of(names);
    }

    @PostMapping(value = "upload")
    public Resp upload(@NotBlank String module, int upType, @NotBlank String prefix, MultipartFile file) throws Exception {

        if (file == null) {
            Resp.fail("没有上传文件");
        }

        String dir = modelServices.getModelDir();
        if (module.indexOf(".") > -1 || module.indexOf("/") > -1) {
            Resp.fail("模块名称不合法");
        }
        dir = dir + module;
        File dirFile = new File(dir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        String content = getContent(file);
        //Zving 模型文件
        if (file.getName().endsWith(".zdm")) {
            Model model = dmServices.loadModel(content);
            for (Table table : model.getTables()) {
                table.setModule(module);
            }
            saveTables(model.getTables(), upType);
        }//Palm 模型
        else if (file.getName().endsWith(".json")) {

        }//Navicat模型
        else if (file.getName().endsWith(".ndm2")) {

        }
        return Resp.ok();
    }
    @Auth(login = false)
    @GetMapping(value="login")
    public Resp login() {
        UserInfo userInfo=new UserInfo();
        userInfo.setPermissions(new HashSet<>(Arrays.asList(DevMenu.MODELS)));
        userInfo.setUsername("dev");
        userInfo.setPassword("dev");
        return Resp.ok(Current.login(userInfo));
    }
}
